home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Prog / T / TIFF Code.cpt / tifflib.c < prev    next >
Text File  |  1987-12-21  |  33KB  |  1,445 lines

  1. /*    
  2.  * tifflib.c - Copyright (c) 1987 by Bear River Associates, Inc.
  3.  *
  4.  *    MPW C Version
  5.  */
  6.  
  7. /* Standard C Include files */
  8. #include "ErrNo.h"
  9. #include "StdIO.h"
  10.  
  11. /* Primary Interface Files */
  12. #include "Types.h"
  13. #include "Resources.h"
  14. #include "Quickdraw.h"
  15. #include "Windows.h"
  16. #include "OSUtils.h"
  17.  
  18. #include "ToolUtils.h"
  19. #include "TextEdit.h"
  20. #include "Controls.h"
  21.  
  22. /* Other Interface files */
  23. #include "Dialogs.h"
  24. #include "Errors.h"
  25. #include "Events.h"
  26. #include "Files.h"
  27. #include "Memory.h"
  28. #include "Packages.h"
  29.  
  30. /* Application-specific Include files */
  31. #include    "tifflib.h"
  32.  
  33. /* Local Routine Declarations */
  34. OSErr    InsertTag();
  35. OSErr    HdlInsertTag();
  36. OSErr    DeleteTag();
  37. OSErr    GStripArrays();
  38. OSErr    PutStripArrays();
  39. OSErr    GStripParams();
  40. void    ParseTag();
  41. void    SwapWord();
  42. void    SwapLong();
  43.  
  44. /* External Routine Declarations */
  45. OSErr    AllocPtr();
  46. OSErr    AllocMemory();
  47. OSErr    AllocHandleSize();
  48.  
  49. /* **************************************************************** */
  50.  
  51. TIFFLoader()
  52. {
  53. }
  54.  
  55. /* ------------------------------------------------------------------- */
  56.  
  57. /*
  58.  *    Writes or re-writes the header; the value of dirOffset
  59.  *    is the offset of the first directory.
  60.  */
  61.  
  62. OSErr TWriteHeader(refNum, dirOffset, byteOrder)
  63. Int16 refNum;
  64. Int32 dirOffset;    /* offset of first directory */
  65. Int16 byteOrder;
  66. {
  67.     OSErr error;
  68.     TiffHeader header;
  69.     Int32 count;
  70.     
  71.     error = noErr;
  72.     
  73.     header.byteOrder = byteOrder;
  74.     header.version = LEGAL_VERSION;
  75.     header.dirOffset = dirOffset;
  76.     if (byteOrder == INTEL)
  77.         {
  78.         SwapWord(&header.version);
  79.         SwapLong(&header.dirOffset);
  80.         }
  81.     
  82.     error = SetFPos(refNum, fsFromStart, 0L);
  83.     
  84.     count = sizeof(TiffHeader);
  85.     if (error == noErr)
  86.         error = FSWrite(refNum, &count, &header);
  87.     
  88.     return(error);
  89. }
  90.  
  91. /* ------------------------------------------------------------------- */
  92.  
  93. /*
  94.  * Reads header, returns offset of the first image file directory and the
  95.  * byte order of the file.
  96.  */
  97.  
  98. OSErr TReadHeader(refNum, dirOffset, byteOrder)
  99. Int16 refNum;
  100. Int32 *dirOffset;
  101. Int16 *byteOrder;
  102. {
  103.     OSErr error;
  104.     TiffHeader header;
  105.     Int32 count;
  106.     
  107.     error = SetFPos(refNum, fsFromStart, 0L);
  108.     
  109.     count = sizeof(TiffHeader);
  110.     if (error == noErr)
  111.         error = FSRead(refNum, &count, &header);
  112.     
  113.     if (header.byteOrder == INTEL)
  114.         SwapLong(&header.dirOffset);
  115.     *dirOffset = header.dirOffset;
  116.     *byteOrder = header.byteOrder;
  117.     
  118.     return(error);
  119. }
  120.  
  121. /* ------------------------------------------------------------------- */
  122.  
  123. /*
  124.  * Add tag to list.  If tag already present, update length and value.
  125.  * This routine keeps tags in correct order in list.
  126.  */
  127.  
  128. OSErr TPutPtrTag(listHandle, tagNo, tagType, nVals, value)
  129. Handle listHandle;
  130. Int16 tagNo;
  131. Int16 tagType;
  132. Int32 nVals;
  133. unsigned char *value;
  134. {
  135.     Int32 pointer;
  136.     OSErr error;
  137.     
  138.     error = noErr;
  139.     
  140.     pointer = 0L;
  141.     if (TFindTag(listHandle, &pointer, tagNo))
  142.         error = DeleteTag(listHandle, pointer);
  143.     
  144.     if (error == noErr)
  145.         error = InsertTag(listHandle, pointer, tagNo, tagType, nVals, value);
  146.     return(error);
  147. }
  148.  
  149. /* ------------------------------------------------------------------- */
  150.  
  151. /*
  152.  * Add tag to list.  Value for tag is in a handle block.
  153.  * If tag already present, update length and value.
  154.  * This routine keeps tags in correct order in list.
  155.  */
  156.  
  157. OSErr TPutHdlTag(listHandle, tagNo, tagType, nVals, valueHdl)
  158. Handle listHandle;
  159. Int16 tagNo;
  160. Int16 tagType;
  161. Int32 nVals;
  162. unsigned char **valueHdl;
  163. {
  164.     Int32 pointer;
  165.     OSErr error;
  166.     
  167.     error = noErr;
  168.     
  169.     pointer = 0L;
  170.     if (TFindTag(listHandle, &pointer, tagNo))
  171.         error = DeleteTag(listHandle, pointer);
  172.     
  173.     if (error == noErr)
  174.         error = HdlInsertTag(listHandle, pointer, tagNo, tagType,
  175.             nVals, valueHdl);
  176.     return(error);
  177. }
  178.  
  179. /* ------------------------------------------------------------------- */
  180.  
  181. /*
  182.  * Searches list for tag of specified number.
  183.  * If found, returns TRUE, and pointer contains offset of tag in list.
  184.  * If not found, returns FALSE, and pointer contains offset in list where
  185.  * tag would be inserted.
  186.  */
  187.  
  188. Boolean TFindTag(listHandle, pointer, tagNo)
  189. Handle listHandle;
  190. Int32 *pointer;
  191. Int16 tagNo;
  192. {
  193.     Boolean done;
  194.     Int32 listSize;
  195.     Int16 thisTagNo;
  196.     Int16 tagType;
  197.     Int32 length;
  198.     Int32 nVals;
  199.     
  200.     *pointer = 0L;
  201.     listSize = GetHandleSize(listHandle);
  202.     
  203.     done = FALSE;
  204.     while (*pointer < listSize && !done)
  205.             {
  206.             ParseTag(listHandle, *pointer, &thisTagNo, &tagType, &nVals);
  207.             switch(tagType)
  208.                 {
  209.                 case BYTE:
  210.                     length = nVals * BYTESIZE;
  211.                     break;
  212.                 case ASCII:
  213.                     length = nVals * ASCIISIZE;
  214.                     break;
  215.                 case SHORT:
  216.                     length = nVals * SHORTSIZE;
  217.                     break;
  218.                 case LONG:
  219.                     length = nVals * LONGSIZE;
  220.                     break;
  221.                 case RATIONAL:
  222.                     length = nVals * RATSIZE;
  223.                     break;
  224.                 default:
  225.                     done = TRUE;
  226.                     break;
  227.                 }
  228.             if (thisTagNo < tagNo)
  229.                 (*pointer) += 8 + length;
  230.             else
  231.                 done = TRUE;
  232.             }
  233.     
  234.     return(done && (tagNo == thisTagNo));    
  235. }
  236.  
  237. /* ------------------------------------------------------------------- */
  238.  
  239. /*
  240.  * Returns value of tag.  Tag is specified by listHandle and pointer.
  241.  */
  242.  
  243. void TGetTag(listHandle, pointer, value, valueSize)
  244. Handle listHandle;
  245. Int32 pointer;
  246. Ptr value;
  247. Int32 valueSize;
  248. {
  249.     Int16 tagNo;
  250.     Int16 tagType;
  251.     Int32 length;
  252.     Int32 nVals;
  253.     Int32 i;
  254.     Ptr listPtr;
  255.     Ptr valuePtr;
  256.     
  257.     
  258.     ParseTag(listHandle, pointer, &tagNo, &tagType, &nVals);
  259.     switch(tagType)
  260.         {
  261.         case BYTE:
  262.             length = nVals * BYTESIZE;
  263.             break;
  264.         case ASCII:
  265.             length = nVals * ASCIISIZE;
  266.             break;
  267.         case SHORT:
  268.             length = nVals * SHORTSIZE;
  269.             break;
  270.         case LONG:
  271.             length = nVals * LONGSIZE;
  272.             break;
  273.         case RATIONAL:
  274.             length = nVals * RATSIZE;
  275.             break;
  276.         default:
  277.             length = 0L;
  278.             break;
  279.         }
  280.     
  281.     valuePtr = value;
  282.     listPtr = *listHandle + pointer + 8;    /* DEREFERENCING HANDLE */
  283.     for (i=0; i<length && i<valueSize; i++)
  284.         *valuePtr++ = *listPtr++; 
  285. }
  286.  
  287. /* ------------------------------------------------------------------- */
  288.  
  289. /*
  290.  * Read tags from file, from directory at offset thisDirPointer.
  291.  * Create and return a handle to the tag data.  Return offset to next
  292.  * directory in nextDirPointer.
  293.  */
  294.  
  295. OSErr TReadTags(refNum, byteOrder, listHandle, thisDirPointer, nextDirPointer)
  296. Int16 refNum;
  297. Int16 byteOrder;
  298. Handle *listHandle;
  299. Int32 thisDirPointer;
  300. Int32 *nextDirPointer;
  301. {
  302.     OSErr error;
  303.     Int32 count;
  304.     Int16 entryCount;
  305.     Int16 thisEntry;
  306.     Int16 tagNo;
  307.     Int16 tagType;
  308.     Int32 nVals;
  309.     Int32 length;
  310.     Int32 valOffset;
  311.     Int32 listPointer;
  312.     Int32 nextDirEntry;
  313.     Ptr tempBuffer;
  314.     Int32 k;
  315.     Handle tempHandle;
  316.     
  317.     *listHandle = NIL;
  318.     error = AllocMemory(listHandle, 0L);
  319.     
  320.     if (error == noErr)
  321.         error = SetFPos(refNum, fsFromStart, thisDirPointer);
  322.     
  323.     if (error == noErr)
  324.         {
  325.         count = sizeof(Int16);
  326.         error = FSRead(refNum, &count, &entryCount);
  327.         if (byteOrder == INTEL)
  328.             SwapWord(&entryCount);
  329.         }
  330.     
  331.     
  332.     thisEntry = 0;
  333.     listPointer = 0L;
  334.     nextDirEntry = thisDirPointer + 2;
  335.     while (thisEntry++ < entryCount && error == noErr)
  336.         {
  337.         error = SetFPos(refNum, fsFromStart, nextDirEntry);
  338.         count = 2;
  339.         if (error == noErr)
  340.             error = FSRead(refNum, &count, &tagNo);
  341.         if (byteOrder == INTEL)
  342.             SwapWord(&tagNo);
  343.         count = 2;
  344.         if (error == noErr)
  345.             error = FSRead(refNum, &count, &tagType);
  346.         if (byteOrder == INTEL)
  347.             SwapWord(&tagType);
  348.         count = 4;
  349.         if (error == noErr)
  350.             error = FSRead(refNum, &count, &nVals);
  351.         if (byteOrder == INTEL)
  352.             SwapLong(&nVals);
  353.         switch(tagType)
  354.             {
  355.             case BYTE:
  356.                 length = nVals * BYTESIZE;
  357.                 break;
  358.             case ASCII:
  359.                 length = nVals * ASCIISIZE;
  360.                 break;
  361.             case SHORT:
  362.                 length = nVals * SHORTSIZE;
  363.                 break;
  364.             case LONG:
  365.                 length = nVals * LONGSIZE;
  366.                 break;
  367.             case RATIONAL:
  368.                 length = nVals * RATSIZE;
  369.                 break;
  370.             default:
  371.                 error = -3;
  372.                 break;
  373.             }
  374.         count = 4;
  375.         if (error == noErr)
  376.             error = FSRead(refNum, &count, &valOffset);
  377.         if (length > 4)
  378.             {
  379.             if (byteOrder == INTEL)
  380.                 SwapLong(&valOffset);
  381.             tempBuffer = NIL;
  382.             if (error == noErr)
  383.                 error = AllocPtr(&tempBuffer, length);
  384.             if (error == noErr)
  385.                 error = SetFPos(refNum, fsFromStart, valOffset);
  386.             count = length;
  387.             if (error == noErr)
  388.                 error = FSRead(refNum, &count, tempBuffer);
  389.             if (error == noErr && byteOrder == INTEL)
  390.                 switch(tagType)
  391.                     {
  392.                     case SHORT:
  393.                         for (k=0; k<nVals; k++)
  394.                             SwapWord(&((Int16 *)tempBuffer)[k]);
  395.                         break;
  396.                     case LONG:
  397.                         for (k=0; k<nVals; k++)
  398.                             SwapLong(&((Int32 *)tempBuffer)[k]);
  399.                         break;
  400.                     case RATIONAL:
  401.                         for (k=0; k<nVals; k++)
  402.                             {
  403.                             SwapLong(&((Int32 *)tempBuffer)[2*k]);
  404.                             SwapLong(&((Int32 *)tempBuffer)[2*k + 1]);
  405.                             }
  406.                         break;
  407.                     }
  408.             if (error == noErr)
  409.                 error = TPutPtrTag(*listHandle, tagNo, tagType, nVals, tempBuffer);
  410.             if (tempBuffer != NIL)
  411.                 DisposPtr(tempBuffer);
  412.             }
  413.         else
  414.             {
  415.             if (byteOrder == INTEL)
  416.                 switch(tagType)
  417.                     {
  418.                     case SHORT:
  419.                         for (k=0; k<nVals; k++)
  420.                             SwapWord(&((Int16 *)&valOffset)[k]);
  421.                         break;
  422.                     case LONG:
  423.                         SwapLong(&valOffset);
  424.                         break;
  425.                     }
  426.             if (error == noErr)
  427.                     error = TPutPtrTag(*listHandle, tagNo, tagType,
  428.                         nVals, &valOffset);
  429.             }
  430.         nextDirEntry += 12;    
  431.         }
  432.     
  433.     return(error);
  434. }
  435.  
  436. /* ------------------------------------------------------------------- */
  437.  
  438. /*
  439.  * Write tag data from listHandle out to file, beginning at
  440.  * offset *nextFileFree.  Update nextFileFree to logical end-of-file.
  441.  * Put nextDirPointer at end of tag directory as value of offset to
  442.  * the next tag directory.
  443.  */
  444.  
  445. OSErr TWriteTags(refNum, byteOrder, nextFileFree, listHandle, nextDirPointer)
  446. Int16 refNum;
  447. Int16 byteOrder;
  448. Int32 *nextFileFree;
  449. Handle *listHandle;
  450. Int32 nextDirPointer;
  451. {
  452.     OSErr error;
  453.     Int32 count;
  454.     Int32 listSize;
  455.     Int16 tagNo;
  456.     Int16 tagType;
  457.     Int32 length;
  458.     Int32 nVals;
  459.     Int16 thisEntry;
  460.     Int16 entryCount;
  461.     Int32 listPointer;
  462.     Int32 nextDirEntry;
  463.     UInt32 valOffset;
  464.     Int32 i;
  465.     Int32 k;
  466.     UInt16 temp16;
  467.     UInt32 temp32;
  468.     Ptr tempPtr;
  469.     Handle tempHandle;
  470.     
  471.     error = noErr;
  472.     
  473.     listPointer = 0L;
  474.     listSize = GetHandleSize(listHandle);
  475.     
  476.     /* count the number of directory entries (number of tags) */
  477.     entryCount = 0;
  478.     while (listPointer < listSize && error == noErr)
  479.             {
  480.             ParseTag(listHandle, listPointer, &tagNo, &tagType, &nVals);
  481.             switch(tagType)
  482.                 {
  483.                 case BYTE:
  484.                     length = nVals * BYTESIZE;
  485.                     break;
  486.                 case ASCII:
  487.                     length = nVals * ASCIISIZE;
  488.                     break;
  489.                 case SHORT:
  490.                     length = nVals * SHORTSIZE;
  491.                     break;
  492.                 case LONG:
  493.                     length = nVals * LONGSIZE;
  494.                     break;
  495.                 case RATIONAL:
  496.                     length = nVals * RATSIZE;
  497.                     break;
  498.                 default:
  499.                     error = -3;
  500.                     break;
  501.                 }
  502.             listPointer += 8 + length;
  503.             entryCount++;
  504.             }
  505.     
  506.     if (error == noErr)
  507.         error = SetFPos(refNum, fsFromStart, *nextFileFree);
  508.     
  509.     count = 2;
  510.     temp16 = entryCount;
  511.     if (byteOrder == INTEL)
  512.         SwapWord(&temp16);
  513.     if (error == noErr)
  514.         error = FSWrite(refNum, &count, &temp16);
  515.     
  516.     /* offset for the first tag to be written */
  517.     nextDirEntry = *nextFileFree + 2;
  518.     /* set nexFileFree to point past this IFD */
  519.     *nextFileFree += 2 + entryCount * 12 + 4;
  520.     count = entryCount * 12 + 4;
  521.     /* expand file to fit IFD */
  522.     if (error == noErr)
  523.         error = SetEOF(refNum, *nextFileFree);
  524.     
  525.     /* write out the tags */
  526.     thisEntry = 0;
  527.     listPointer = 0L;
  528.     while (thisEntry++ < entryCount && error == noErr)
  529.         {
  530.         error = SetFPos(refNum, fsFromStart, nextDirEntry);
  531.         ParseTag(listHandle, listPointer, &tagNo, &tagType, &nVals);
  532.         switch(tagType)
  533.             {
  534.             case BYTE:
  535.                 length = nVals * BYTESIZE;
  536.                 break;
  537.             case ASCII:
  538.                 length = nVals * ASCIISIZE;
  539.                 break;
  540.             case SHORT:
  541.                 length = nVals * SHORTSIZE;
  542.                 break;
  543.             case LONG:
  544.                 length = nVals * LONGSIZE;
  545.                 break;
  546.             case RATIONAL:
  547.                 length = nVals * RATSIZE;
  548.                 break;
  549.             default:
  550.                 error = -3;
  551.                 break;
  552.             }
  553.         count = 2;
  554.         temp16 = tagNo;
  555.         if (byteOrder == INTEL)
  556.             SwapWord(&temp16);
  557.         if (error == noErr)
  558.             error = FSWrite(refNum, &count, &temp16);
  559.     
  560.         count = 2;
  561.         temp16 = tagType;
  562.         if (byteOrder == INTEL)
  563.             SwapWord(&temp16);
  564.         if (error == noErr)
  565.             error = FSWrite(refNum, &count, &temp16);
  566.     
  567.         count = 4;
  568.         temp32 = nVals;
  569.         if (byteOrder == INTEL)
  570.             SwapLong(&temp32);
  571.         if (error == noErr)
  572.             error = FSWrite(refNum, &count, &temp32);
  573.             
  574.         if (length <= 4)    /* put actual value in directory entry */
  575.             {
  576.             valOffset = 0L;
  577.             TGetTag(listHandle, listPointer, &valOffset, length);
  578.     
  579.             count = 4;
  580.             temp32 = valOffset;
  581.             if (byteOrder == INTEL)
  582.                 {
  583.                 switch(tagType)
  584.                     {
  585.                     case SHORT:
  586.                         for (k=0; k<nVals; k++)
  587.                             SwapWord(&((Int16 *)&temp32)[k]);
  588.                         break;
  589.                     case LONG:
  590.                         SwapLong(&temp32);
  591.                         break;
  592.                     }
  593.                 }
  594.             if (error == noErr)
  595.                 error = FSWrite(refNum, &count, &temp32);
  596.             }
  597.         else                /* offset of value goes in directory entry */
  598.             {
  599.             valOffset = *nextFileFree;
  600.             count = 4;
  601.             temp32 = valOffset;
  602.             if (byteOrder == INTEL)
  603.                 SwapLong(&temp32);
  604.             if (error == noErr)
  605.                 error = FSWrite(refNum, &count, &temp32);
  606.             if (error == noErr)
  607.                 error = SetFPos(refNum, fsFromStart, *nextFileFree);
  608.             count = length;
  609.             tempPtr = NIL;
  610.             if (error == noErr)
  611.                 error = AllocPtr(&tempPtr, length);
  612.             if (error == noErr)
  613.                 TGetTag(listHandle, listPointer, tempPtr, length);
  614.             if (error == noErr && byteOrder == INTEL)
  615.                 switch(tagType)
  616.                     {
  617.                     case SHORT:
  618.                         for (k=0; k<nVals; k++)
  619.                             SwapWord(&((Int16 *)tempPtr)[k]);
  620.                         break;
  621.                     case LONG:
  622.                         for (k=0; k<nVals; k++)
  623.                             SwapLong(&((Int32 *)tempPtr)[k]);
  624.                         break;
  625.                     case RATIONAL:
  626.                         for (k=0; k<nVals; k++)
  627.                             {
  628.                             SwapLong(&((Int32 *)tempPtr)[2*k]);
  629.                             SwapLong(&((Int32 *)tempPtr)[2*k + 1]);
  630.                             }
  631.                         break;
  632.                     }
  633.             if (error == noErr)
  634.                 error = FSWrite(refNum, &count, tempPtr);
  635.             *nextFileFree += length;
  636.             if (tempPtr != NIL)
  637.                 DisposPtr(tempPtr);
  638.             }
  639.         nextDirEntry += 12;
  640.         listPointer += 8 + length;
  641.         }
  642.     
  643.     if (error == noErr)
  644.         error = SetFPos(refNum, fsFromStart, nextDirEntry);
  645.     count = 4;
  646.     temp32 = nextDirPointer;
  647.     if (byteOrder == INTEL)
  648.         SwapLong(&temp32);
  649.     if (error == noErr)
  650.         error = FSWrite(refNum, &count, &temp32);
  651.     
  652.     return(error);    
  653. }
  654.  
  655. /* ------------------------------------------------------------------- */
  656.  
  657. /*
  658.  * Reads in "numLines" lines from the file starting with line number
  659.  * "startLine".  The data for the lines will be places at the address
  660.  * specified by bufferPtr.
  661.  */
  662. OSErr TReadImage(refNum, listHandle, startLine, bufferPtr, numLines, plane)
  663. Int16 refNum;
  664. Handle listHandle;
  665. Int32 startLine;
  666. Ptr bufferPtr;
  667. Int32 numLines;
  668. Int16 plane;        /* ignored, for now */
  669. {
  670.     Handle countHandle;
  671.     Handle offsetHandle;
  672.     OSErr error;
  673.     Int32 pointer;
  674.     Int32 tRowsPerStrip;
  675.     Int16 tRowBytes;
  676.     Int16 bitsPerSample;
  677.     Int16 imageWidth;
  678.     Int16 imageLength;
  679.     Int16 compressType;
  680.     Int16 firstStrip;
  681.     Int16 lastStrip;
  682.     Int16 stripNum;
  683.     Ptr stripPtr;
  684.     Ptr dummyPtr;
  685.     Int32 stripSize;
  686.     Int32 stripOffset;
  687.     Ptr srcPtr;
  688.     Ptr dstPtr;
  689.     register Ptr rSrcPtr;
  690.     register Ptr rDstPtr;
  691.     Int32 count;
  692.     Int16 i;
  693.     Int32 thisLine;
  694.     Handle tempHandle;
  695.     
  696.     error = GStripArrays(listHandle, &offsetHandle, &countHandle);
  697.     
  698.     if (error == noErr)
  699.         error = GStripParams(listHandle, &tRowsPerStrip,
  700.             &imageWidth, &imageLength, &compressType, &bitsPerSample);
  701.     
  702.     tRowBytes = ((Int32)imageWidth * bitsPerSample + 7) / 8;
  703.         /* NOTE! this can be an odd number, unlike bitMap.rowBytes */
  704.     
  705.     dummyPtr = NIL;
  706.     if (error == noErr)
  707.         error = AllocPtr(&dummyPtr, (Int32)tRowBytes);
  708.     
  709.     if (error == noErr)
  710.         {
  711.         firstStrip = startLine / tRowsPerStrip;
  712.         lastStrip = (startLine + numLines - 1) / tRowsPerStrip;
  713.         thisLine = firstStrip * tRowsPerStrip;
  714.         for (stripNum = firstStrip; stripNum <= lastStrip && error == noErr;
  715.                 stripNum++)
  716.             {
  717.             stripSize = (*(Int32 **)countHandle)[stripNum];
  718.             stripOffset = (*(Int32 **)offsetHandle)[stripNum];
  719.             stripPtr = NIL;
  720.             error = AllocPtr(&stripPtr, stripSize);
  721.             if (error == noErr)
  722.                 error = SetFPos(refNum, fsFromStart, stripOffset);
  723.             if (error == noErr)
  724.                 {
  725.                 count = stripSize;
  726.                 error = FSRead(refNum, &count, stripPtr);
  727.                 }
  728.             if (error == noErr)
  729.                 {
  730.                 srcPtr = stripPtr;
  731.                 while (srcPtr < stripPtr + stripSize &&
  732.                         thisLine < startLine + numLines && error == noErr)
  733.                     {
  734.                     if (thisLine < startLine)
  735.                         dstPtr = dummyPtr;
  736.                     else if (thisLine == startLine)
  737.                         dstPtr = bufferPtr;
  738.                     switch (compressType)
  739.                         {
  740.                         case 1:
  741.                             rSrcPtr = srcPtr;
  742.                             rDstPtr = dstPtr;
  743.                             for (i=0; i<tRowBytes; i++)
  744.                                 *rDstPtr++ = *rSrcPtr++;
  745.                             srcPtr = rSrcPtr;
  746.                             dstPtr = rDstPtr;
  747.                             break;
  748.     
  749.                         case 2:
  750.                             error = HDecode(&dstPtr, &srcPtr, imageWidth);
  751.                             break;
  752.     
  753.                         default:
  754.                             error = -3;
  755.                             break;
  756.                         }
  757.                     thisLine++;
  758.                     }
  759.                 }
  760.             if (stripPtr != NIL)
  761.                 DisposPtr(stripPtr);
  762.             }
  763.         }
  764.     
  765.     if (offsetHandle != NIL)
  766.         DisposHandle(offsetHandle);
  767.     if (countHandle != NIL)
  768.         DisposHandle(countHandle);
  769.     if (dummyPtr != NIL)
  770.         DisposPtr(dummyPtr);
  771.     
  772.     return(error);
  773. }
  774.  
  775. /* ------------------------------------------------------------------- */
  776.  
  777. /*
  778.  * Writes image data for ONE strip.  startpos must be start of a strip.
  779.  * numLines must be <= tRowsPerStrip.
  780.  * Strip parameters (rowsPerStrip, imageWidth,
  781.  * compressType and imageLength) must already have tags
  782.  */
  783.  
  784. OSErr TWriteImageStrip(refNum, nextFileFree, listHandle,
  785.      startLine, numLines, bufferPtr, plane)
  786. Int16 refNum;
  787. Int32 *nextFileFree;
  788. Handle listHandle;
  789. Int32 startLine;
  790. Int32 numLines;
  791. Ptr bufferPtr;
  792. Int16 plane;
  793. {
  794.     OSErr error;
  795.     OSErr tempErr;
  796.     Int32 ** offsetHandle;
  797.     Int32 ** countHandle;
  798.     Int16 stripNum;
  799.     Int16 numStrips;
  800.     Int16 row;
  801.     Int16 i;
  802.     Int32 tRowsPerStrip;
  803.     Int16 tRowBytes;
  804.     Int16 bitsPerSample;
  805.     Int16 imageWidth;
  806.     Int16 imageLength;
  807.     Int16 compressType;
  808.     Int32 stripSize;
  809.     Int32 count;
  810.     Ptr srcPtr;
  811.     Ptr dstPtr;
  812.     register Ptr rSrcPtr;
  813.     register Ptr rDstPtr;
  814.     Ptr rowBuffer;
  815.     Int32 thisLine;
  816.     Handle tempHandle;
  817.     
  818.     error = noErr;
  819.     if (GStripArrays(listHandle, &offsetHandle, &countHandle) != noErr)
  820.         {  /* if offsetHandle and countHandle don't exist, then create them */
  821.         error = AllocMemory(&offsetHandle, 0L);
  822.         if (error == noErr)
  823.             error = AllocMemory(&countHandle, 0L);
  824.         }
  825.     if (error == noErr)
  826.         error = GStripParams(listHandle, &tRowsPerStrip, &imageWidth,
  827.             &imageLength, &compressType, &bitsPerSample);
  828.     
  829.     if (tRowsPerStrip > imageLength)
  830.         tRowsPerStrip = imageLength;
  831.     
  832.     stripNum = startLine / tRowsPerStrip;
  833.     
  834.     if (error == noErr)
  835.         {
  836.         numStrips = GetHandleSize(offsetHandle) / sizeof(Int32);
  837.         if (stripNum >= numStrips)
  838.             {
  839.             error = AllocHandleSize(offsetHandle,
  840.                                     (Size)(stripNum + 1) * sizeof(Int32));
  841.             if (error == noErr)
  842.                 error = AllocHandleSize(countHandle,
  843.                                         (Size)(stripNum + 1) * sizeof(Int32));
  844.             if (error == noErr)
  845.                 for (i=numStrips; i<stripNum; i++)
  846.                     (*countHandle)[i] = 0L;
  847.             }
  848.         }
  849.     
  850.     tRowBytes = (imageWidth * bitsPerSample + 7) / 8;
  851.         /* NOTE! this can be an odd number, unlike bitMap.rowBytes */
  852.     
  853.     rowBuffer = NIL;
  854.     if (error == noErr)
  855.         error = AllocPtr(&rowBuffer, 2 * (Int32)tRowBytes); 
  856.     
  857.     if (error == noErr)
  858.         {
  859.         (*offsetHandle)[stripNum] = *nextFileFree;
  860.         stripSize = 0L;
  861.         srcPtr = bufferPtr;
  862.         error = SetFPos(refNum, fsFromStart, *nextFileFree);
  863.         for (row=0; row<tRowsPerStrip && row<numLines && error == noErr; row++)
  864.             {
  865.             dstPtr = rowBuffer;
  866.             switch (compressType)
  867.                 {
  868.                 case 1:
  869.                     rSrcPtr = srcPtr;
  870.                     rDstPtr = dstPtr;
  871.                     for (i=0; i<tRowBytes; i++)
  872.                         *rDstPtr++ = *rSrcPtr++;
  873.                     srcPtr = rSrcPtr;
  874.                     dstPtr = rDstPtr;
  875.                     count = tRowBytes;
  876.                     break;
  877.     
  878.                 case 2:
  879.                     error = HEncode(&srcPtr, &dstPtr, imageWidth);
  880.                     count = dstPtr - rowBuffer;
  881.                     break;
  882.     
  883.                 default:
  884.                     error = -3;
  885.                     break;
  886.                 }
  887.             if (error == noErr)
  888.                 error = FSWrite(refNum, &count, rowBuffer);
  889.             *nextFileFree += count;
  890.             stripSize += count;
  891.             }
  892.         (*countHandle)[stripNum] = stripSize;
  893.         }
  894.     
  895.     if (rowBuffer != NIL)
  896.         DisposPtr(rowBuffer);
  897.     
  898.     tempErr = PutStripArrays(listHandle, offsetHandle, countHandle);
  899.     if (error == noErr)
  900.         error = tempErr;
  901.     return(error);
  902. }
  903.  
  904. /* ---------------------------------------------------------------- */
  905.  
  906. void TFixOddRowBytes(bitMap)
  907. BitMap *bitMap;
  908. {
  909.     register Ptr dstPtr;
  910.     register Ptr srcPtr;
  911.     Int32 nLines;
  912.     Int16 line;
  913.     Int16 k;
  914.     
  915.     nLines = bitMap->bounds.bottom - bitMap->bounds.top;
  916.     srcPtr = bitMap->baseAddr + nLines * (bitMap->rowBytes - 1) - 1;
  917.     dstPtr = bitMap->baseAddr + nLines * bitMap->rowBytes - 2;
  918.     for (line=nLines; line>0; line--)
  919.         {
  920.         for (k=0; k<bitMap->rowBytes-1; k++)
  921.             *dstPtr-- = *srcPtr--;
  922.         dstPtr--;
  923.         }
  924. }
  925.  
  926. /* ---------------------------------------------------------------- */
  927.  
  928. void TUnfixOddRowBytes(bitMap)
  929. BitMap *bitMap;
  930. {
  931.     register Ptr dstPtr;
  932.     register Ptr srcPtr;
  933.     Int32 nLines;
  934.     Int16 line;
  935.     Int16 k;
  936.     
  937.     nLines = bitMap->bounds.bottom - bitMap->bounds.top;
  938.     srcPtr = bitMap->baseAddr;
  939.     dstPtr = bitMap->baseAddr;
  940.     for (line=0; line<nLines; line++)
  941.         {
  942.         for (k=0; k<bitMap->rowBytes-1; k++)
  943.             *dstPtr++ = *srcPtr++;
  944.         srcPtr++;
  945.         }
  946. }
  947.  
  948. /* ------------------------------------------------------------------- */
  949. /*                            Local Subroutines                           */
  950. /* ------------------------------------------------------------------- */
  951.  
  952. /*
  953.  * Remove the tag beginning at the specified offset.  Reduce the size
  954.  * of the list accordingly.
  955.  */
  956.  
  957. static OSErr DeleteTag(listHandle, pointer)
  958. Handle listHandle;
  959. Int32 pointer;
  960. {
  961.     Int32 listSize;
  962.     Int16 tagNo;
  963.     Int16 tagType;
  964.     Int32 length;
  965.     Int32 nVals;
  966.     Int16 tagSize;
  967.     unsigned char *listPtr;
  968.     Int32 i;
  969.     OSErr error;
  970.     Handle tempHandle;
  971.     
  972.     listSize = GetHandleSize(listHandle);
  973.     ParseTag(listHandle, pointer, &tagNo, &tagType, &nVals);
  974.     switch(tagType)
  975.         {
  976.         case BYTE:
  977.             length = nVals * BYTESIZE;
  978.             break;
  979.         case ASCII:
  980.             length = nVals * ASCIISIZE;
  981.             break;
  982.         case SHORT:
  983.             length = nVals * SHORTSIZE;
  984.             break;
  985.         case LONG:
  986.             length = nVals * LONGSIZE;
  987.             break;
  988.         case RATIONAL:
  989.             length = nVals * RATSIZE;
  990.             break;
  991.         }
  992.     tagSize = length + 8;
  993.     
  994.     listPtr = *listHandle;    /* DEREFERENCING HANDLE */
  995.     for (i=pointer; i<listSize-tagSize; i++)
  996.         listPtr[i] = listPtr[i + tagSize];
  997.     
  998.     error = AllocHandleSize(listHandle, listSize - tagSize);
  999.     return(error);
  1000. }
  1001.  
  1002. /* ------------------------------------------------------------------- */
  1003.  
  1004. /*
  1005.  * Insert tag in list.  This routine does not check for duplicates.
  1006.  */
  1007.  
  1008. static OSErr InsertTag(listHandle, pointer, tagNo, tagType, nVals, value)
  1009. Handle listHandle;
  1010. Int32 pointer;
  1011. Int16 tagNo;
  1012. Int16 tagType;
  1013. Int32 nVals;
  1014. unsigned char *value;
  1015. {
  1016.     OSErr error;
  1017.     Int32 listSize;
  1018.     Int32 tagSize;
  1019.     unsigned char *listPtr;
  1020.     Int32 i;
  1021.     Int32 length;
  1022.     Handle tempHandle;
  1023.     
  1024.     listSize = GetHandleSize(listHandle);
  1025.     switch(tagType)
  1026.         {
  1027.         case BYTE:
  1028.             length = nVals * BYTESIZE;
  1029.             break;
  1030.         case ASCII:
  1031.             length = nVals * ASCIISIZE;
  1032.             break;
  1033.         case SHORT:
  1034.             length = nVals * SHORTSIZE;
  1035.             break;
  1036.         case LONG:
  1037.             length = nVals * LONGSIZE;
  1038.             break;
  1039.         case RATIONAL:
  1040.             length = nVals * RATSIZE;
  1041.             break;
  1042.         default:
  1043.             error = -3;
  1044.             break;
  1045.         }
  1046.     tagSize = length + 8;
  1047.     error = AllocHandleSize(listHandle, listSize + tagSize);
  1048.     
  1049.     if (error == noErr)
  1050.         {
  1051.         listPtr = *listHandle;    /* DEREFERENCING HANDLE */
  1052.         for (i=listSize+tagSize-1; i>=pointer+tagSize; i--)
  1053.             listPtr[i] = listPtr[i - tagSize];
  1054.         listPtr += pointer;
  1055.         *listPtr++ = (tagNo >> 8) & 0xff;
  1056.         *listPtr++ = (tagNo) & 0xff;
  1057.         *listPtr++ = (tagType >> 8) & 0xff;
  1058.         *listPtr++ = (tagType) & 0xff;
  1059.         *listPtr++ = (nVals >> 24) & 0xff;
  1060.         *listPtr++ = (nVals >> 16) & 0xff;
  1061.         *listPtr++ = (nVals >> 8) & 0xff;
  1062.         *listPtr++ = (nVals) & 0xff;
  1063.         for (i=0; i<length; i++)
  1064.             *listPtr++ = value[i];
  1065.         }
  1066.     
  1067.     return(error);
  1068. }
  1069.  
  1070. /* ------------------------------------------------------------------- */
  1071.  
  1072. /*
  1073.  * Insert tag in list.  value is stored in a handle block.
  1074.  * This routine does not check for duplicates.
  1075.  */
  1076.  
  1077. static OSErr HdlInsertTag(listHandle, pointer, tagNo, tagType, nVals, valueHdl)
  1078. Handle listHandle;
  1079. Int32 pointer;
  1080. Int16 tagNo;
  1081. Int16 tagType;
  1082. Int32 nVals;
  1083. unsigned char **valueHdl;
  1084. {
  1085.     OSErr error;
  1086.     Int32 listSize;
  1087.     Int32 tagSize;
  1088.     unsigned char *listPtr;
  1089.     Int32 i;
  1090.     Int32 length;
  1091.     Handle tempHandle;
  1092.     
  1093.     listSize = GetHandleSize(listHandle);
  1094.     switch(tagType)
  1095.         {
  1096.         case BYTE:
  1097.             length = nVals * BYTESIZE;
  1098.             break;
  1099.         case ASCII:
  1100.             length = nVals * ASCIISIZE;
  1101.             break;
  1102.         case SHORT:
  1103.             length = nVals * SHORTSIZE;
  1104.             break;
  1105.         case LONG:
  1106.             length = nVals * LONGSIZE;
  1107.             break;
  1108.         case RATIONAL:
  1109.             length = nVals * RATSIZE;
  1110.             break;
  1111.         default:
  1112.             error = -3;
  1113.             break;
  1114.         }
  1115.     tagSize = length + 8;
  1116.     error = AllocHandleSize(listHandle, listSize + tagSize);
  1117.     
  1118.     if (error == noErr)
  1119.         {
  1120.         listPtr = *listHandle;    /* DEREFERENCING HANDLE */
  1121.         for (i=listSize+tagSize-1; i>=pointer+tagSize; i--)
  1122.             listPtr[i] = listPtr[i - tagSize];
  1123.         listPtr += pointer;
  1124.         *listPtr++ = (tagNo >> 8) & 0xff;
  1125.         *listPtr++ = (tagNo) & 0xff;
  1126.         *listPtr++ = (tagType >> 8) & 0xff;
  1127.         *listPtr++ = (tagType) & 0xff;
  1128.         *listPtr++ = (nVals >> 24) & 0xff;
  1129.         *listPtr++ = (nVals >> 16) & 0xff;
  1130.         *listPtr++ = (nVals >> 8) & 0xff;
  1131.         *listPtr++ = (nVals) & 0xff;
  1132.         for (i=0; i<length; i++)
  1133.             *listPtr++ = (&**valueHdl)[i];
  1134.         }
  1135.     
  1136.     return(error);
  1137. }
  1138.  
  1139. /* ------------------------------------------------------------------- */
  1140.  
  1141. static void ParseTag(listHandle, pointer, tagNo, tagType, nVals)
  1142. Handle listHandle;
  1143. Int32 pointer;
  1144. Int16 *tagNo;
  1145. Int16 *tagType;
  1146. Int32 *nVals;
  1147. {
  1148.     unsigned char *listPtr;
  1149.     
  1150.     listPtr = *listHandle + pointer;    /* DEREFERENCING HANDLE */
  1151.     *tagNo = ((UInt16)listPtr[0] << 8) + (UInt16)listPtr[1];
  1152.     *tagType = ((UInt16)listPtr[2] << 8) + (UInt16)listPtr[3];
  1153.     *nVals = ((UInt32)listPtr[4] << 24) + (UInt32)(listPtr[5] << 16) +
  1154.         ((UInt32)listPtr[6] << 8) + (UInt32)listPtr[7];
  1155. }
  1156.  
  1157. /* ------------------------------------------------------------------- */
  1158.  
  1159. /*
  1160.  * Create and return handles to arrays containg the strip byte counts
  1161.  * and strip offsets
  1162.  */
  1163.  
  1164. static OSErr GStripArrays(listHandle, offsetHandle, countHandle)
  1165. Handle listHandle;
  1166. Handle *offsetHandle;
  1167. Handle *countHandle;
  1168. {
  1169.     OSErr error;
  1170.     Int32 pointer;
  1171.     Int16 tagNo;
  1172.     Int16 tagType;
  1173.     Int32 length;
  1174.     Int32 numOffsets;
  1175.     Int32 nVals;
  1176.     Int32 tRowsPerStrip;
  1177.     Int16 imageWidth;
  1178.     Int16 imageLength;
  1179.     Int16 compressType;
  1180.     Int16 bitsPerSample;
  1181.     Int32 theByteCount;
  1182.     Int32 i;
  1183.     UInt8 *temp8Ptr;
  1184.     UInt16 *temp16Ptr;
  1185.     UInt32 *temp32Ptr;
  1186.     
  1187.     *countHandle = NIL;
  1188.     *offsetHandle = NIL;
  1189.     
  1190.     error = noErr;
  1191.     
  1192.     
  1193.     /* .................................... */
  1194.     
  1195.     if (error == noErr)
  1196.         error = TFindTag(listHandle, &pointer, STRIP_OFFSETS_TAG) ?
  1197.             noErr : -3;
  1198.     
  1199.     if (error == noErr)
  1200.         {
  1201.         ParseTag(listHandle, pointer, &tagNo, &tagType, &numOffsets);
  1202.         length = numOffsets * LONGSIZE;
  1203.         error = AllocMemory(offsetHandle, length);
  1204.         }
  1205.     
  1206.     if (error == noErr)
  1207.         {
  1208.         HLock(*offsetHandle);
  1209.         TGetTag(listHandle, pointer, **offsetHandle, length);
  1210.         /* convert array bytes or shorts to array of longs in place */
  1211.         switch(tagType)
  1212.             {
  1213.             case BYTE:
  1214.                 /* HANDLE DEREFERENCE */
  1215.                 temp8Ptr = (*(UInt8 **)(*offsetHandle)) + numOffsets - 1;
  1216.                 temp32Ptr = (*(UInt32 **)(*offsetHandle)) + numOffsets - 1;
  1217.                 for (i = numOffsets - 1; i >= 0; i--)
  1218.                     *temp32Ptr-- = *temp8Ptr--;
  1219.                 break;
  1220.             case SHORT:
  1221.                 /* HANDLE DEREFERENCE */
  1222.                 temp16Ptr = (*(UInt16 **)(*offsetHandle)) + numOffsets - 1;
  1223.                 temp32Ptr = (*(UInt32 **)(*offsetHandle)) + numOffsets - 1;
  1224.                 for (i = numOffsets - 1; i >= 0; i--)
  1225.                     *temp32Ptr-- = *temp16Ptr--;
  1226.                 break;
  1227.             case LONG:
  1228.                 break;
  1229.             default:
  1230.                 error = -3;
  1231.                 break;
  1232.             }
  1233.         HUnlock(*offsetHandle);
  1234.         }
  1235.     
  1236.     /* .................................... */
  1237.     
  1238.     if (error == noErr)
  1239.         {
  1240.         error = TFindTag(listHandle, &pointer, STRIP_BYTE_COUNTS_TAG) ? noErr : -3;
  1241.         if (error == noErr)
  1242.             {    /* STRIP_BYTE_COUNTS_TAG exists */
  1243.             ParseTag(listHandle, pointer, &tagNo, &tagType, &nVals);
  1244.             length = nVals * LONGSIZE;
  1245.             error = AllocMemory(countHandle, length);
  1246.             if (error == noErr)
  1247.                 {
  1248.                 HLock(*countHandle);
  1249.                 TGetTag(listHandle, pointer, **countHandle, length);
  1250.                 /* convert array bytes or shorts to array of longs in place */
  1251.                 switch(tagType)
  1252.                     {
  1253.                     case BYTE:
  1254.                         /* HANDLE DEREFERENCE */
  1255.                         temp8Ptr = (*(UInt8 **)(*countHandle)) + nVals - 1;
  1256.                         temp32Ptr = (*(UInt32 **)(*countHandle)) + nVals - 1;
  1257.                         for (i = nVals - 1; i >= 0; i--)
  1258.                             *temp32Ptr-- = *temp8Ptr--;
  1259.                         break;
  1260.                     case SHORT:
  1261.                         /* HANDLE DEREFERENCE */
  1262.                         temp16Ptr = (*(UInt16 **)(*countHandle)) + nVals - 1;
  1263.                         temp32Ptr = (*(UInt32 **)(*countHandle)) + nVals - 1;
  1264.                         for (i = nVals - 1; i >= 0; i--)
  1265.                             *temp32Ptr-- = *temp16Ptr--;
  1266.                         break;
  1267.                     case LONG:
  1268.                         break;
  1269.                     default:
  1270.                         error = -3;
  1271.                         break;
  1272.                     }
  1273.                 HUnlock(*countHandle);
  1274.                 }
  1275.             }
  1276.         else
  1277.             {    /* STRIP_BYTE_COUNTS_TAG does not exist */
  1278.                 /* we are ok if file is not compressed and there is only one strip */
  1279.             error = GStripParams(listHandle, &tRowsPerStrip, &imageWidth, &imageLength,
  1280.                 &compressType, &bitsPerSample);
  1281.             /* nVals and length determined above */
  1282.             
  1283.             if (error == noErr && compressType == 1 && numOffsets == 1)
  1284.                 {    /* OK.  fake the count array */
  1285.                 error = AllocMemory(countHandle, length);
  1286.                 if (error == noErr)
  1287.                     {
  1288.                     theByteCount = (Int32)imageWidth * (Int32)imageLength *
  1289.                         (Int32)bitsPerSample / 8L;
  1290.                     **(Int32 **)(*countHandle) = theByteCount;
  1291.                     }
  1292.                 }
  1293.             else
  1294.                 error = -3;
  1295.             }
  1296.         }
  1297.     
  1298.     
  1299.     /* .................................... */
  1300.     
  1301.     return(error);
  1302. }
  1303.  
  1304. /* ------------------------------------------------------------------- */
  1305.  
  1306. /*
  1307.  * Delete old tags (if they exist) and add new tags for
  1308.  * StripByteCounts and StripOffsets.  In all cases, offsetHandle and
  1309.  * countHandle are disposed, if they are not NIL
  1310.  */
  1311.  
  1312. static OSErr PutStripArrays(listHandle, offsetHandle, countHandle)
  1313. Handle listHandle;
  1314. Handle offsetHandle;
  1315. Handle countHandle;
  1316. {
  1317.     OSErr error;
  1318.     Int32 pointer;
  1319.     Int16 tagNo;
  1320.     Int16 tagType;
  1321.     Int32 length;
  1322.     Int32 nVals;
  1323.     
  1324.     if (TFindTag(listHandle, &pointer, STRIP_BYTE_COUNTS_TAG))
  1325.         DeleteTag(listHandle, pointer);
  1326.     
  1327.     if (TFindTag(listHandle, &pointer, STRIP_OFFSETS_TAG))
  1328.         DeleteTag(listHandle, pointer);
  1329.     
  1330.     error = countHandle == NIL ? -3 : noErr;
  1331.     if (error == noErr)
  1332.         {
  1333.         length = GetHandleSize(countHandle);
  1334.         nVals = length / LONGSIZE;
  1335.         /*MoveHHi(countHandle);
  1336.         HLock(countHandle);*/
  1337.         error = TPutHdlTag(listHandle, STRIP_BYTE_COUNTS_TAG, LONG,
  1338.             nVals, countHandle);
  1339.         /*HUnlock(countHandle);*/
  1340.         }
  1341.     
  1342.     if (error == noErr)
  1343.         error = offsetHandle == NIL ? -3 : noErr;
  1344.     
  1345.     if (error == noErr)
  1346.         {
  1347.         length = GetHandleSize(offsetHandle);
  1348.         nVals = length / LONGSIZE;
  1349.         /*MoveHHi(offsetHandle);
  1350.         HLock(offsetHandle);*/
  1351.         error = TPutHdlTag(listHandle, STRIP_OFFSETS_TAG, LONG,
  1352.             nVals, offsetHandle);
  1353.         /*HUnlock(offsetHandle);*/
  1354.         }
  1355.     
  1356.     if (countHandle != NIL)
  1357.         DisposHandle(countHandle);
  1358.     if (offsetHandle != NIL)
  1359.         DisposHandle(offsetHandle);
  1360.     
  1361.     return(error);
  1362. }
  1363.  
  1364.  
  1365. /* ------------------------------------------------------------------- */
  1366.  
  1367. /*
  1368.  * Read data from the tag data list (listHandle) and return the
  1369.  * values.  If the tags are missing, return -3 as error.
  1370.  */
  1371.  
  1372. static OSErr GStripParams(listHandle, tRowsPerStrip, imageWidth, imageLength,
  1373.     compressType, bitsPerSample)
  1374. Handle listHandle;
  1375. Int32 *tRowsPerStrip;
  1376. Int16 *imageWidth;
  1377. Int16 *imageLength;
  1378. Int16 *compressType;
  1379. Int16 *bitsPerSample;
  1380. {
  1381.     OSErr error;
  1382.     OSErr tempError;
  1383.     Int32 pointer;
  1384.     
  1385.     tempError = TFindTag(listHandle, &pointer, ROWS_PER_STRIP_TAG) ?
  1386.             noErr : -3;
  1387.     if (tempError == noErr)
  1388.         TGetTag(listHandle, pointer, tRowsPerStrip, (Int32)LONGSIZE);
  1389.     else
  1390.         *tRowsPerStrip = 0x40000000;    /* default */
  1391.     
  1392.     tempError = TFindTag(listHandle, &pointer, BITS_PER_SAMPLE_TAG) ?
  1393.             noErr : -3;
  1394.     if (tempError == noErr)
  1395.         TGetTag(listHandle, pointer, bitsPerSample, (Int32)SHORTSIZE);
  1396.     else
  1397.         *bitsPerSample = 1;    /* default */
  1398.     
  1399.     tempError = TFindTag(listHandle, &pointer, COMPRESSION_TAG) ?
  1400.             noErr : -3;
  1401.     
  1402.     if (tempError == noErr)
  1403.         TGetTag(listHandle, pointer, compressType, (Int32)SHORTSIZE);
  1404.     else
  1405.         *compressType = 1;        /* default */
  1406.     
  1407.     error = TFindTag(listHandle, &pointer, IMAGE_WIDTH_TAG) ?
  1408.             noErr : -3;
  1409.     
  1410.     if (error == noErr)
  1411.         TGetTag(listHandle, pointer, imageWidth, (Int32)SHORTSIZE);
  1412.     
  1413.     if (error == noErr)
  1414.         error = TFindTag(listHandle, &pointer, IMAGE_LENGTH_TAG) ?
  1415.             noErr : -3;
  1416.     
  1417.     if (error == noErr)
  1418.         TGetTag(listHandle, pointer, imageLength, (Int32)SHORTSIZE);
  1419.     
  1420.     
  1421.     return(error);
  1422. }
  1423.  
  1424. /* ------------------------------------------------------------------- */
  1425.  
  1426. void SwapWord(val)
  1427. UInt16 *val;
  1428. {
  1429.     *val = (*val >> 8) + (*val << 8);
  1430. }
  1431.  
  1432. /* ------------------------------------------------------------------- */
  1433.  
  1434. void SwapLong(val)
  1435. UInt16 val[2];
  1436. {
  1437.     UInt16 temp;
  1438.     
  1439.     temp = val[0];
  1440.     val[0] = (val[1] >> 8) + (val[1] << 8);
  1441.     val[1] = (temp >> 8) + (temp << 8);
  1442. }
  1443.  
  1444. /* ------------------------------------------------------------------- */
  1445.